package org.hibernate.dialect;

import java.sql.Types;
import org.hibernate.Hibernate;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.VarArgsSQLFunction;

/** 
 * La clase {@code SQLiteDialect} plantea un dialecto de hibernate para utilizar
 * con la base de datos SQLite. Se plantean las diferentes realaciones de tipos
 * entre la base de datos e hibernate, métodos auxiliares para denotar las
 * capacidades de la base de datos, entre otras cosas.
 * 
 * @see Dialect
 * @author Arno Raps 
 */
public class SQLiteDialect extends Dialect {

    public SQLiteDialect() {
        super();
        registerColumnType( Types.BIT, "integer" );
        registerColumnType( Types.TINYINT, "tinyint" );
        registerColumnType( Types.SMALLINT, "smallint" );
        registerColumnType( Types.INTEGER, "integer" );
        registerColumnType( Types.BIGINT, "bigint" );
        registerColumnType( Types.FLOAT, "float" );
        registerColumnType( Types.REAL, "real" );
        registerColumnType( Types.DOUBLE, "double" );
        registerColumnType( Types.NUMERIC, "numeric" );
        registerColumnType( Types.DECIMAL, "decimal" );
        registerColumnType( Types.CHAR, "char" );
        registerColumnType( Types.VARCHAR, "varchar" );
        registerColumnType( Types.LONGVARCHAR, "longvarchar" );
        registerColumnType( Types.DATE, "date" );
        registerColumnType( Types.TIME, "time" );
        registerColumnType( Types.TIMESTAMP, "timestamp" );
        registerColumnType( Types.BINARY, "blob" );
        registerColumnType( Types.VARBINARY, "blob" );
        registerColumnType( Types.LONGVARBINARY, "blob" );
        registerColumnType( Types.BLOB, "blob" );
        registerColumnType( Types.CLOB, "clob" );
        registerColumnType( Types.BOOLEAN, "integer" );

        registerFunction( "concat", new VarArgsSQLFunction( Hibernate.STRING, "", "||", "" ) );
        registerFunction( "mod", new SQLFunctionTemplate( Hibernate.INTEGER, "?1 % ?2" ) );
        registerFunction( "substr", new StandardSQLFunction( "substr", Hibernate.STRING ) );
        registerFunction( "substring", new StandardSQLFunction( "substr", Hibernate.STRING ) );
    }

    @Override
    public boolean supportsIdentityColumns() {
        return true;
    }

    @Override
    public boolean hasDataTypeInIdentityColumn() {
        return false;
    }

    @Override
    public String getIdentityColumnString() {
        return "integer";
    }

    @Override
    public String getIdentitySelectString() {
        return "select last_insert_rowid()";
    }

    @Override
    public boolean supportsLimit() {
        return true;
    }

    @Override
    protected String getLimitString( String query, boolean hasOffset ) {
        return new StringBuffer( query.length() + 20 ).append( query ).
                append( hasOffset ? " limit ? offset ?" : " limit ?" ).
                toString();
    }

    @Override
    public boolean supportsTemporaryTables() {
        return true;
    }

    @Override
    public String getCreateTemporaryTableString() {
        return "create temporary table if not exists";
    }

    @Override
    public boolean dropTemporaryTableAfterUse() {
        return false;
    }

    @Override
    public boolean supportsCurrentTimestampSelection() {
        return true;
    }

    @Override
    public boolean isCurrentTimestampSelectStringCallable() {
        return false;
    }

    @Override
    public String getCurrentTimestampSelectString() {
        return "select current_timestamp";
    }

    @Override
    public boolean supportsUnionAll() {
        return true;
    }

    @Override
    public boolean hasAlterTable() {
        return false;
    }

    @Override
    public boolean dropConstraints() {
        return false;
    }

    @Override
    public String getAddColumnString() {
        return "add column";
    }

    @Override
    public String getForUpdateString() {
        return "";
    }

    @Override
    public boolean supportsOuterJoinForUpdate() {
        return false;
    }

    @Override
    public String getDropForeignKeyString() {
        throw new UnsupportedOperationException( "No drop foreign key syntax supported by SQLiteDialect" );
    }

    @Override
    public String getAddForeignKeyConstraintString( String constraintName, String[] foreignKey, String referencedTable, String[] primaryKey, boolean referencesPrimaryKey ) {
        throw new UnsupportedOperationException( "No add foreign key syntax supported by SQLiteDialect" );
    }

    @Override
    public String getAddPrimaryKeyConstraintString( String constraintName ) {
        throw new UnsupportedOperationException( "No add primary key syntax supported by SQLiteDialect" );
    }

    @Override
    public boolean supportsIfExistsBeforeTableName() {
        return true;
    }

    @Override
    public boolean supportsCascadeDelete() {
        return false;
    }

}//end clase SQLiteDialect

